/**
* Oxide
*
* Copyright (c) 2011 Dinosaur Kick Pty Ltd, All rights reserved.
*
* This source code is made available under the "Modified BSD" licensing arrangement.
* See license.txt for details.
*/
// ----------------------------------------------------------------------------
#include <stack>
#include "../ast/ast_fwd.hpp"
// ----------------------------------------------------------------------------
#ifndef O2_RENDERER_CSTYLE_RENDERER
#define O2_RENDERER_CSTYLE_RENDERER
namespace o2 {
namespace renderer {
// ----------------------------------------------------------------------------

template <typename DerivedT, typename StringT>
class basic_cstyle_renderer
	: public ast::basic_visitor<DerivedT, StringT, StringT>
{
	public:
		typedef StringT string_type;
		typedef typename string_type::value_type char_type;
		O2_AST_TYPEDEFS(string_type);
		
		basic_cstyle_renderer(void)
			: m_block_operators(O2_CSTR("{}()[]"))
			{ assert(m_block_operators.size() % 2 == 0); }

		basic_cstyle_renderer(const string_type& block_operators)
			: m_block_operators(block_operators)
			{ assert(m_block_operators.size() % 2 == 0); }

	protected:
		string_type indent(void) const
			{ return string_type(m_block_stack.size() * 4, ' '); }

		string_type open_block(char_type ch) const
		{
			assert(m_block_operators.find(ch) != string_type::npos);
			assert(m_block_operators.find(ch) % 2 == 0);
			string_type result = indent() + ch + O2_STR("\n");
			m_block_stack.push(ch);
			return result;
		}
		
		string_type close_block(void) const
		{
			size_t pos = m_block_operators.find(m_block_stack.top());
			m_block_stack.pop();
			return indent() + m_block_operators[pos + 1] + O2_CSTR("\n");
		}

	private:
		const string_type m_block_operators;
		mutable std::stack<char_type> m_block_stack;
};

// ----------------------------------------------------------------------------
} // namespace renderer
} // namespace o2
#endif // O2_RENDERER_CSTYLE_RENDERER
// ----------------------------------------------------------------------------
